#ifndef __PVMSYSTEM_H__
#define __PVMSYSTEM_H__

#include "pvm/pvmtypes.h"
#include "pvm/pvmdefs.h"

#include <stdio.h>


#if (defined(WIN32) || defined(_WINDOWS)) && !defined(PVM_USE_POSIX) &&!defined(SHP)
#include "lib/sys/windows/pvmosdep.h"
#endif

#if defined(PVM_USE_POSIX)
#include "lib/sys/posix/pvmosdep.h"
#endif

#if defined(__SYMBIAN32__)
#include "lib/sys/symbian/pvmosdep.h"
#endif

#if defined(SHP)
#include "lib/sys/bada/pvmosdep.h"
#endif

#if defined(IW_PLATFORM_S3E)
#include "lib/sys/marmalade/pvmosdep.h"
#endif

#if defined(TIZEN)
#include "lib/sys/tizen/pvmosdep.h"
#endif

//***
//Common threading functions
pvm_bool PVMIsThreadSyncAvailable();
pvm_bool PVMIsThreadsAvailable();

//***
//Critical sections
#if defined(_DEBUG) && defined(USE_CRITICAL_WATCH)

#include "lib/memory/pvmmemory.h"

class CriticalWatch : public PVMAllocableObject
{
protected:
	PVMCriticalSection* target;

public:
	CriticalWatch(PVMCriticalSection* c);
	~CriticalWatch();
	void Remove(PVMCriticalSection* c);
};

#endif

pvm_bool PVMInitCritical(PVMCriticalSection *critical);
void PVMDeinitCritical(PVMCriticalSection *critical);

#if defined(_DEBUG) && defined(DEBUG_CRITICAL_SECTIONS)
pvm_bool PVMEnterCriticalD(PVMCriticalSection *critical, char* file, int line);
void PVMLeaveCriticalD(PVMCriticalSection *critical);

#ifdef USE_CRITICAL_WATCH
#define PVMEnterCritical(a) CriticalWatch __crwatch(a); PVMEnterCriticalD(a, __FILE__, __LINE__)
#define PVMLeaveCritical(a) __crwatch.Remove(a); PVMLeaveCriticalD(a)
#else
#define PVMEnterCritical(a) PVMEnterCriticalD(a, __FILE__, __LINE__)
#define PVMLeaveCritical(a) PVMLeaveCriticalD(a)
#endif
#else
pvm_bool PVMEnterCritical(PVMCriticalSection *critical);
void PVMLeaveCritical(PVMCriticalSection *critical);
#endif

//***
//Events
pvm_bool PVMInitEvent(PVMEventHandle *event);
void PVMDeinitEvent(PVMEventHandle *event);
pvm_bool PVMWaitForEvent(PVMEventHandle *event);
void PVMSignalEvent(PVMEventHandle *event);



//***
//Threads
void PVMInitThreadVar(PVMThreadHandle* outHandle);
pvm_bool PVMIsThreadValid(PVMThreadHandle threadHandle);
pvm_bool PVMCreateThread(PVMThreadHandle* outHandle, PVMThreadStartRoutine routine, void *param);
int PVMJoinThread(PVMThreadHandle threadHandle);

void PVMSleep(pvm_uint32 sleepTime);

pvm_uint32 PVMGetMilliSecondsCount();


//***
//File IO
enum TPvmFileMode
{
	PVM_READ = 1,
	PVM_WRITE = 2,
	PVM_CREATE_ALWAYS = 4,
	PVM_OPEN_EXISTING = 8,
	PVM_OPEN_ALWAYS = 16,
};

PVMFileHandle PVMFileOpen(const pvm_char* fileName, pvm_int32 mode);
void PVMFileClose(PVMFileHandle file);
pvm_bool PVMFileRead(PVMFileHandle file, void* buffer, pvm_size nBytes, pvm_size* readResult);
pvm_bool PVMFileWrite(PVMFileHandle file, void* buffer, pvm_size nBytes, pvm_size* writeResult);
pvm_file_size PVMFileSize(PVMFileHandle file);
pvm_bool PVMFileSeek(PVMFileHandle file, pvm_file_size pos, pvm_int32 origin);
pvm_file_size PVMFileTell(PVMFileHandle file);
pvm_bool PVMFileEOF(PVMFileHandle file);

void PVMSysLogOutString(const pvm_char* logString);

//***
//Init/deinit
pvm_bool PVMSystemInit();
void PVMSystemDeinit();
#endif

